package com.googlecode.animator.controller.mediators
{
	import com.googlecode.animator.data.Notifications;
	import com.googlecode.animator.data.cameras.ActualViewCameraVO;
	import com.googlecode.animator.data.cameras.CameraVO;
	import com.googlecode.animator.data.cameras.FrontViewCameraVO;
	import com.googlecode.animator.data.cameras.LeftViewCameraVO;
	import com.googlecode.animator.data.cameras.MainViewCameraVO;
	import com.googlecode.animator.data.cameras.TopViewCameraVO;
	import com.googlecode.animator.data.markers.GlobalMarkerVO;
	import com.googlecode.animator.data.objects3d.CameraProxyVO;
	import com.googlecode.animator.data.objects3d.CubeVO;
	import com.googlecode.animator.data.objects3d.Object3DVO;
	import com.googlecode.animator.data.objects3d.PlaneVO;
	import com.googlecode.animator.data.objects3d.SphereVO;
	import com.googlecode.animator.data.objects3d.TargetProxyVO;
	import com.googlecode.animator.data.viewports.ViewportVO;
	
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.mediator.Mediator;

	public class OpenProjectMediator extends Mediator
	{
		/**
		 * Name prefix used to create dynamic mediator names.
		 * Names will be appended by the INSTANCE_COUNT to create a unique mediator name. 
		 */
		protected static const NAME_PREFIX:String = "OpenProjectMediator_";
		
		/**
		 * Counter indicating how many instances of this class have been created. 
		 */		
		protected static var INSTANCE_COUNT:uint = 0;
		
		protected var _path:String;
		
		protected var _projectXML:XML;
		
		public function OpenProjectMediator(path:String)
		{
			super(NAME_PREFIX + INSTANCE_COUNT);
			
			_path = path;
			// update instance count so we obtain a unique name for each Mediator instance
			INSTANCE_COUNT++;
		}
		
		override public function onRegister():void
		{
			sendNotification(Notifications.RESET_PROJECT);
		}
		
		override public function listNotificationInterests():Array
		{
			var list:Array = super.listNotificationInterests();
			
			list.push(Notifications.PROJECT_IS_RESET);
			list.push(Notifications.DEFAULT_VIEWPORTS_ADDED);
			
			return list;
		}
		
		override public function handleNotification(notification:INotification):void
		{
			super.handleNotification(notification);
			
			switch(notification.getName())
			{
				case Notifications.PROJECT_IS_RESET:
					
					handleProjectIsReset();
					
					break;
					
				case Notifications.DEFAULT_VIEWPORTS_ADDED:
					
					handleDefaultViewportsAdded();
					
					break; 
			}
		}
		
		protected function handleProjectIsReset():void
		{
			// load the default XML for the project
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE, onProjectXMLLoaded);
			loader.addEventListener(IOErrorEvent.IO_ERROR, onError);
	
			var url:URLRequest = new URLRequest(_path);
			loader.load(url);
		}
		
		protected function onProjectXMLLoaded(evt:Event):void
		{
			(evt.target as URLLoader).removeEventListener(Event.COMPLETE, onProjectXMLLoaded);
			(evt.target as URLLoader).removeEventListener(IOErrorEvent.IO_ERROR, onError);
			
			_projectXML = new XML(((evt.target) as URLLoader).data);
			
			
			var vVO:ViewportVO;
			
			for each(var viewport:XML in _projectXML.viewports.viewport)
			{
				vVO = new ViewportVO();
				vVO.fromXML(viewport);
				
				sendNotification(Notifications.ADD_VIEWPORT, vVO);
			} 
			
		}
		
		protected function onError(evt:IOErrorEvent):void
		{
			(evt.target as URLLoader).removeEventListener(Event.COMPLETE, onProjectXMLLoaded);
			(evt.target as URLLoader).removeEventListener(IOErrorEvent.IO_ERROR, onError);
			
			facade.removeMediator(getMediatorName());
		}
		
		protected function handleDefaultViewportsAdded():void
		{
			var cameraVO:CameraVO;
			//sendNotification(Notifications.ADD_DEFAULT_CAMERAS, _projectXML);
			for each(var camera:XML in _projectXML.cameras.*)
			{
				if(camera.name() == ActualViewCameraVO.TYPE)
				{
					cameraVO = new ActualViewCameraVO();
					cameraVO.fromXML(camera);
					
					sendNotification(Notifications.ADD_CAMERA, cameraVO as ActualViewCameraVO);
				}
				
				if(camera.name() == MainViewCameraVO.TYPE)
				{
					cameraVO = new MainViewCameraVO();
					cameraVO.fromXML(camera);
					
					sendNotification(Notifications.ADD_CAMERA, cameraVO as MainViewCameraVO);
				}
				
				if(camera.name() == TopViewCameraVO.TYPE)
				{
					cameraVO = new TopViewCameraVO();
					cameraVO.fromXML(camera);
					
					sendNotification(Notifications.ADD_CAMERA, cameraVO as TopViewCameraVO);
				}
				
				if(camera.name() == LeftViewCameraVO.TYPE)
				{
					cameraVO = new LeftViewCameraVO();
					cameraVO.fromXML(camera);
					
					sendNotification(Notifications.ADD_CAMERA, cameraVO as LeftViewCameraVO);
				}
				
				if(camera.name() == FrontViewCameraVO.TYPE)
				{
					cameraVO = new FrontViewCameraVO();
					cameraVO.fromXML(camera);
					
					sendNotification(Notifications.ADD_CAMERA, cameraVO as FrontViewCameraVO);
				}
			}

			// now add everything else
			var globalMarker:GlobalMarkerVO;
			
			for each(var gMarker:XML in _projectXML.globalMarkers.globalMarker)
			{
				globalMarker = new GlobalMarkerVO();
				globalMarker.fromXML(gMarker);
				
				sendNotification(Notifications.TIMELINE_ADD_GLOBAL_MARKER, globalMarker);
			}
			
			var o3D:Object3DVO
			
			for each(var object3D:XML in _projectXML.objects3D.*)
			{
				if(object3D.name() == CameraProxyVO.TYPE)
				{
					o3D = new CameraProxyVO();
					o3D.fromXML(object3D);
					
					sendNotification(Notifications.ADD_OBJECT3D, o3D as CameraProxyVO);	
				}
				
				if(object3D.name() == TargetProxyVO.TYPE)
				{
					o3D = new TargetProxyVO();
					o3D.fromXML(object3D);
					
					sendNotification(Notifications.ADD_OBJECT3D, o3D as TargetProxyVO);	
				}
				
				if(object3D.name() == SphereVO.TYPE)
				{
					o3D = new SphereVO();
					o3D.fromXML(object3D);
					
					sendNotification(Notifications.ADD_OBJECT3D, o3D as SphereVO);
				}
				
				if(object3D.name() == PlaneVO.TYPE)
				{
					o3D = new PlaneVO();
					o3D.fromXML(object3D);
					
					sendNotification(Notifications.ADD_OBJECT3D, o3D as PlaneVO);
				} 
				
				if(object3D.name() == CubeVO.TYPE)
				{
					o3D = new CubeVO();
					o3D.fromXML(object3D);

					sendNotification(Notifications.ADD_OBJECT3D, o3D as CubeVO);	
				}

			}
			
			//sendNotification(Notifications.OBJECT3D_SELECTED, o3D.name);
			
			facade.removeMediator(getMediatorName());
		}

	}
	
}